#include <QStringList>
#include <QList>
#include "CharType.h"

#include "CodeTable.h"
extern CodeTable Encoder;


const QString REGEXP_SIGN = "re:";
const QString STRING_BEGIN = "^";
const QString ANYDATA = "ANYDATA";

CharType::CharType(const QString& character) 
: _isRegExp(character.startsWith(REGEXP_SIGN))
, _type(DATA)
, _match(NORMAL)
{
    IsRegExp() ? CreateRegExp(character) : CreateCharacterList(character); 
}

void CharType::CreateRegExp(const QString& character)
{
    _regExp.setPatternSyntax(QRegExp::RegExp2);
    _regExp.setPattern(STRING_BEGIN + character.mid(REGEXP_SIGN.size()));
}

void CharType::CreateCharacterList(const QString& character)
{
    QStringList list = character.split("\\", QString::SkipEmptyParts, Qt::CaseInsensitive);

    if (!list.empty())
    {  
        CreateList(list[0], _possible);
        
        if (list.size() == 2)
            CreateList(list[1], _impossible);
        
        _possible -= _impossible;
    }
}

void CharType::CreateList(const QString& list, CharCodeSet& set)
{    
    Q_FOREACH(const QString& c, list.split(",", QString::SkipEmptyParts, Qt::CaseInsensitive))
    {
        int type = DATA;
        
        if (c == ANYDATA)
            _match = (&set == &_possible) ? ANY : NONE;
        else
            set.insert(Encoder.Encode(c, &type));

        _type = qMax(static_cast<EType>(type), _type);
    }
}

const CharCodeSet& CharType::Possible()
{
    return _possible;
}

const CharCodeSet& CharType::Impossible()
{
    return _impossible;
}

void CharType::SetValue(const QByteArray& data)
{
    _value = data;  
}

const QByteArray& CharType::Value()
{
    return _value;
}

CharType::EType CharType::Type()
{
    return _type;
}

CharType::EMatch CharType::Match()
{
    return _match;
}

bool CharType::IsRegExp()
{
    return _isRegExp;
}

QRegExp& CharType::RegExp()
{
    return _regExp;
}
